package com.wjbgn.weatherforecast.service.impl;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.util.StringUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.wjbgn.weatherforecast.config.redis.RedisUtil;
import com.wjbgn.weatherforecast.dto.CityData;
import com.wjbgn.weatherforecast.service.IWeatherService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.util.*;

/**
 * @description： 天气服务实现
 * @author：weirx
 * @date：2022/5/20 16:30
 * @version：3.0
 */
@Slf4j
@Service
public class WeatherServiceImpl implements IWeatherService {
    /**
     * 高德天气地址
     */
    private String url = "https://restapi.amap.com/v3/weather/weatherInfo?key=b2af3673ae3fe0dd3b9681f9faff169a&output=json&extensions=all&city=";

    private final static String FILENAME = "src/main/resources/xlxs/AMap_adcode_citycode_20210406.xlsx";

    private Set<Map<String, String>> set = new HashSet<>();

    @Autowired
    private RedisUtil redisUtil;

    /**
     * description: easyexcel
     *
     * @author: weirx
     * @time: 2022/5/25 15:48
     */
    public class ExcelListener extends AnalysisEventListener<CityData> {
        /**
         * description: 读取每行的数据
         *
         * @param data
         * @param analysisContext
         * @return: void
         * @author: weirx
         * @time: 2022/5/20 16:46
         */
        @Override
        public void invoke(CityData data, AnalysisContext analysisContext) {
            // 设置
            Map<String, String> map = new HashMap<>(4);
            map.put("name", data.getName());
            map.put("code", data.getAdcode());
            set.add(map);
        }

        /**
         * description: 读取表头
         *
         * @param headMap
         * @param context
         * @return: void
         * @author: weirx
         * @time: 2022/5/20 16:46
         */
        @Override
        public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
            System.out.println("表头：" + headMap);
            log.info("表头：{}", JSON.toJSONString(headMap));
        }

        /**
         * description: 读取完毕收尾操作
         *
         * @param analysisContext
         * @return: void
         * @author: weirx
         * @time: 2022/5/20 16:46
         */
        @Override
        public void doAfterAllAnalysed(AnalysisContext analysisContext) {
            Set<Object> city_code = redisUtil.getSet("city_code");
            if (null == city_code || city_code.size() == 0) {
                // TODO 此处比较慢，可优化为使用pipeline的形式
                redisUtil.setSetPipeline("city_info", set);
            } else {
                log.info("已存在，不能再次导入");
            }
        }
    }

    @Override
    public void importCityCode() {
        EasyExcel.read(FILENAME, CityData.class, new ExcelListener()).sheet().doRead();
    }

    @Override
    public String getCityWeather(String cityCode) {
        String result = null;
        String object = redisUtil.getString("city_weather:" + cityCode);
        if (ObjectUtil.isEmpty(object)) {
            result = HttpUtil.createGet(url + cityCode).execute().body();
            redisUtil.setObjectExpire("city_weather:" + cityCode, result, Duration.ofHours(1L));
            log.info(result);
        } else {
            result = object;
        }
        return result;
    }

    @Override
    public List getCityInfo() {
        return redisUtil.getSetPipeline("city_info");
    }

    @Override
    public List<Map<String, Object>> getProvincialCapitalWeather() {
        List cityInfo = this.getCityInfo();
        List<Map<String, Object>> cities = new ArrayList<>();
        Object o = cityInfo.get(0);
        JSONArray objects = JSON.parseArray(JSON.toJSONString(o));
        objects.forEach(city -> {
            JSONObject jsonObject = JSON.parseObject(JSON.toJSONString(city));
            Map<String, Object> map = new HashMap<>();
            String weather = null;
            if (jsonObject.getString("code").contains("0000")) {
                if (jsonObject.getString("name").equals("香港特别行政区") ||
                        jsonObject.get("name").equals("澳门特别行政区")) {
                    weather = this.getCityWeather(JSON.toJSONString(jsonObject.getInteger("code")));
                    map.put("name", jsonObject.getString("name"));
                    map.put("weather", weather);
                } else {
                    weather = this.getCityWeather(JSON.toJSONString(jsonObject.getInteger("code") + 100));
                    map.put("name", jsonObject.getString("name"));
                    map.put("weather", weather);
                }
            }
            if (StringUtils.isNotBlank(weather)) {
                cities.add(map);
            }
        });
        return cities;
    }

}
